package it.ilgrv.demiurgo.control;

import it.ilgrv.demiurgo.persistence.HandleTable;
import it.ilgrv.demiurgo.persistence.tables.character.Character;
import it.ilgrv.demiurgo.persistence.tables.faction.Association;
import it.ilgrv.demiurgo.persistence.tables.inscription.Availableassociation;
import it.ilgrv.demiurgo.persistence.tables.inscription.Meeting;
import it.ilgrv.demiurgo.persistence.tables.inscription.Partecipant;
import it.ilgrv.demiurgo.persistence.tables.inscription.User;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;

public class Inscription extends HandleTable {

	public Inscription(EntityManager em) {
		super(em);
	}

	/**
	 * create a new user
	 * 
	 * @param email
	 * @param password
	 * @param name
	 * @param surname
	 * @param birthdate
	 * @param birthplace
	 * @param contry
	 * @param sex
	 * @param city
	 * @param street
	 * @param zipCode
	 * @param phoneNumber
	 * @param mobilePhoneNumber
	 * @param carNumber
	 * @return
	 */
	public User createUser(
			String email,
			String password,
			String name,
			String surname,
			Date birthdate,
			String birthplace,
			String contry,
			String sex,
			String city,
			String street,
			String zipCode,
			String phoneNumber,
			String mobilePhoneNumber,
			String carNumber
			) {
		User u = null;

		try {
			beginTransaction();

			// TODO handle duplicate email error
			u =
			new User(email, password, name, surname, birthdate, birthplace, contry, sex, city, street,
						zipCode
			);

			u.setZipCode(phoneNumber);
			u.setMobilePhoneNumber(mobilePhoneNumber);
			u.setCarNumber(carNumber);

			em.persist(u);

		} finally {
			endTransaction();
		}

		return u;
	}

	/**
	 * create a new meeting
	 * 
	 * @param name
	 * @param startDate
	 * @param endDate
	 * @param description
	 * @return
	 */
	public Meeting createMeeting(
			String name,
			Date startDate,
			Date endDate,
			String description
			) {

		Meeting meeting = null;
		try {
			beginTransaction();

			meeting = new Meeting(name, startDate, endDate, description);

			em.persist(meeting);

		} finally {
			endTransaction();
		}

		return meeting;
	}
	
	/**
	 * inscribe a user to meeting
	 * 
	 * @param u
	 * @param m
	 * @return
	 */
	public boolean inscribeToMeeting(User u, Character c, Meeting m) {
		if (u == null | m == null) {
			return false;
		}

		Partecipant p;
		try {
			beginTransaction();

			if (isMaxCharactersAlreadyInscribedForUser(u, m)) {
				return false;
			}

			if (Partecipant.isActivePartecipantExist(em, u, c, m)) {
				return false;
			}
			
			p = new Partecipant();

			p.setUser(u);
			u.addPartecipant(p);
			p.setMeeting(m);
			m.addPartecipant(p);

			em.persist(p);

			em.merge(u);
			em.merge(m);

			return true;

		} finally {
			endTransaction();
		}

		// return false;
	}

	/**
	 * remove a user from meeting
	 * 
	 * @param u
	 * @param m
	 * @return
	 */
	public boolean removeFromMeeting(User u, Character c, Meeting m) {
		if (u == null | m == null) {
			return false;
		}

		Partecipant p;
		try {
			beginTransaction();

			if (!Partecipant.isActivePartecipantExist(em, u, c, m)) {
				return false;
			}

			p = Partecipant.getActivePartecipant(em, u, m);
			if (p == null) {
				return false;
			} else {
				p.setInactive(true);
				em.merge(p);
				return true;
			}


		} finally {
			endTransaction();
		}
		
		// return false;
	}

	/**
	 * adds to meeting the available associations in wich a user can inscribe
	 * 
	 * @param m
	 * @param associations
	 */
	public boolean addInscrivableAssociationsForMeeting(Meeting m, List<Association> associations) {

		if (m == null) {
			return false;
		}

		try {
			beginTransaction();

			for (Association a : associations) {
				addAssociationToMeeting(m, a);
			}

			return true;
		} finally {
			endTransaction();
		}
	}

	/**
	 * add an association to be available to be selected be partecipants
	 * 
	 * @param m
	 * @param a
	 * @return
	 */
	public boolean addAssociationToMeeting(Meeting m, Association a) {
		if (m == null || a == null) {
			return false;
		}

		try {
			beginTransaction();
			if (!Availableassociation.isExistAvailableassociation(em, m, a)) {
				Availableassociation aa = new Availableassociation();
				aa.setAssociation(a);
				aa.setMeeting(m);

				em.persist(aa);

				em.merge(a);
				em.merge(m);
				return true;
			}
			
			return false;

		} finally {
			endTransaction();
		}
	}

	/**
	 * check if user U already registered maximum characters for meeting m
	 * 
	 * @param u
	 * @param m
	 * @return true if cannot registered any more, false otherwise
	 */

	private boolean isMaxCharactersAlreadyInscribedForUser(User u, Meeting m) {
		// TODO implementami
		return false;
	}

}
